package ac.svn.accesscontrol.ui.helper;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.swing.JLabel;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import ac.svn.accesscontrol.manager.SVNInfoManager;
import ac.svn.accesscontrol.store.ISVNItem;
import ac.svn.accesscontrol.store.SVNGroup;
import ac.svn.accesscontrol.store.SVNUser;
import ac.svn.accesscontrol.ui.IUIConstants;
import ac.svn.accesscontrol.ui.UIComponentLibrary;

/**
 * @author Enigmanic
 *
 */
public class TreePopulator implements ILister
{
	private boolean listClrRequired = false;
	private Thread listingThread;
	private Set<ISVNItem> sourceFiles;
	private JTree svnTree;
	private DefaultMutableTreeNode rootNode;
	private JLabel statusLabel;

	public TreePopulator(String componentId,String rootNodeId)
	{
		svnTree = (JTree) UIComponentLibrary.getComponent(componentId);
		rootNode =  (DefaultMutableTreeNode) UIComponentLibrary.getComponent(rootNodeId);
		statusLabel = (JLabel) UIComponentLibrary.getComponent(IUIConstants.C_STATUS_LABEL);		

		listingThread = new Thread(new Runnable() {
			@Override
			public void run() {
				synchronized (rootNode) {

					Map<String,DefaultMutableTreeNode> allNodes = new HashMap<String, DefaultMutableTreeNode>();
					Map<String,Set<String>> group2UserMap = new HashMap<String, Set<String>>();

					if(null == sourceFiles || sourceFiles.isEmpty())
					{
						return;
					}

					rootNode = new DefaultMutableTreeNode("");

					DefaultTreeModel defaultTreeModel = (DefaultTreeModel) svnTree.getModel();
					defaultTreeModel.setRoot(rootNode);

					if(isListClrRequired())
					{
						rootNode.removeAllChildren();
					}

					for(ISVNItem  svnItem  : sourceFiles )
					{
						SVNGroup svnGroup = (SVNGroup) svnItem;
						DefaultMutableTreeNode groupNode = (DefaultMutableTreeNode) UIComponentLibrary.getComponent(String.format("%s",svnGroup.getGroupAlias()));
						if(null == groupNode)
						{
							groupNode = new DefaultMutableTreeNode(svnGroup);
						}					
						groupNode.setUserObject(svnGroup);
						groupNode.removeAllChildren();

						allNodes.put(svnGroup.getGroupAlias(),groupNode);
						Set<String> allUsers = new TreeSet<String>();
						for(String userAlias: svnGroup.getGroupMembers())
						{
							SVNUser svnUser = SVNInfoManager.getInfoManager().getSvnUser(userAlias);
							DefaultMutableTreeNode userNode = new DefaultMutableTreeNode(svnUser);
							String key = svnUser.getName() + "#"  +svnGroup.getGroupAlias();
							UIComponentLibrary.addComponent(key, userNode);						
							allNodes.put(key, userNode);
							allUsers.add(svnUser.getUserAlias());
						}
						group2UserMap.put(svnGroup.getGroupAlias(), allUsers);
						UIComponentLibrary.addComponent(svnGroup.getGroupAlias(), groupNode);
					}

					List<String> list = new ArrayList<String>(group2UserMap.keySet());
					Collections.sort(list);
					for(String group: list)
					{
						DefaultMutableTreeNode gn = allNodes.get(group);
						Set<String> allMembers = group2UserMap.get(group);
						for(String user: allMembers)
						{
							String key = user + "#" + group;
							DefaultMutableTreeNode un = allNodes.get(key);
							gn.add(un);
						}
						rootNode.add(gn);					
					}
				}

				SwingUtilities.invokeLater(new Runnable() {
					@Override
					public void run() {
						synchronized (svnTree) {
							SwingUtilities.updateComponentTreeUI(svnTree);
							if(isListClrRequired())
							{
								statusLabel.setText("Listing complete!");
							}					
						}
					}
				});
			}
		});
	}

	public void listItems(Set<ISVNItem> svnItems)
	{
		sourceFiles = null;
		sourceFiles =  svnItems;
		refresh();
	}

	public void setListClrRequired(boolean listClrRequired) {
		this.listClrRequired = listClrRequired;
	}

	public boolean isListClrRequired() {
		return listClrRequired;
	}

	public void refresh()
	{
		if(listingThread.isAlive())
		{
			listingThread.interrupt();
		}
		listingThread.run();
	}

	public void addItem(ISVNItem svnItem)
	{
		sourceFiles.add(svnItem);
		refresh();
	}

}
